/*
 * @Author: your name
 * @Date: 2020-06-28 12:43:01
 * @LastEditTime: 2020-06-28 12:43:50
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /facerecognition/src/CtrlCPU/VideoDecoder/VideoDecoder.h
 */
/*
 * Copyright(C) 2020. Huawei Technologies Co.,Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __VIDEO_DECODER__
#define __VIDEO_DECODER__

#include "ModuleBase/ModuleBase.h"
#include "ConfigParser/ConfigParser.h"
#include "acl/acl_rt.h"
#include "DataTrans/DataTrans.pb.h"
#include "DvppCommon/DvppCommon.h"
#include "MemoryPool/MemoryPool.h"
#include <unistd.h>
#include <atomic>
#ifdef ASCEND_FACE_USE_HI_MPI
#include "acl/dvpp/hi_dvpp.h"
#else
#include "acl/ops/acl_dvpp.h"
#endif

namespace ascendFaceRecognition {
struct VdecInfo {
    std::shared_ptr<uint8_t> streamData;
    std::shared_ptr<uint8_t> imageData;
    uint32_t streamSize;
    uint32_t imageSize;
    uint64_t frameId;
};

struct FrameOutputSize {
    uint32_t width;
    uint32_t height;
};

class VideoDecoder : public ModuleBase {
public:
    VideoDecoder();

    ~VideoDecoder();

    APP_ERROR Init(ConfigParser &configParser, ModuleInitArgs &initArgs);

    APP_ERROR DeInit(void);

    static bool stopDecoderThread;
#ifndef ASCEND_FACE_USE_HI_MPI
    static pthread_t decoderThreadId;
    static int stopCount;
    static int instanceCount;
    static int decoderThreadSignal;
    static int deviceStatus;
#endif

protected:
    APP_ERROR Process(std::shared_ptr<void> inputData);

private:
    std::shared_ptr<uint8_t> AclrtMallocAndCopy(StreamDataTrans streamData);

    APP_ERROR ParseConfig(ConfigParser &configParser);

    APP_ERROR InitVdec();

    APP_ERROR DeInitVdec();

    APP_ERROR VideoDecode(std::shared_ptr<VdecInfo> &vdecInfo);

    APP_ERROR CreateThread();

    APP_ERROR CreateVdecChn(hi_vdec_chn_attr& chnAttr, int &channelId);

#ifdef ASCEND_FACE_USE_HI_MPI
    void SetChannelAttribute(hi_vdec_chn_attr &chnAttr);

    APP_ERROR ReSetChannelParm(hi_vdec_chn_param &chnParam);

    static void* vdecThread(void* arg);

    static void GetFrameAiInfoAndSendData(VideoDecoder* videoDecoder, hi_video_frame_info &frame);

#else
    static void* DecoderThread(void* arg);

    APP_ERROR SendFrameAsync(std::shared_ptr<VdecInfo> vdecInfo, acldvppStreamDesc* dvppStreamDesc,
                             void* decoderH26xInfo);

    static void VideoDecoderCallback(acldvppStreamDesc* input, acldvppPicDesc* output, void* userData);
#endif
private:
    FrameInfo frameInfo;
    uint64_t frameId_ = 0;
    uint32_t streamWidthMax_ = 1920;
    uint32_t streamHeightMax_ = 1080;
    uint32_t originalWidth_ = 0;
    uint32_t originalHeight_ = 0;
    uint32_t skipInterval_ = 3;
    std::string videoFormat_;
    std::shared_ptr<aclvdecChannelDesc> vdecChannelDesc_ = nullptr;
    std::shared_ptr<MemoryPool> memPoolOrigin_ = nullptr;
#ifdef ASCEND_FACE_USE_HI_MPI
    pthread_t vdecThreadId_ = 0;
    hi_payload_type videoType_ = HI_PT_H264;
#else
    acldvppStreamFormat videoType_ = H264_MAIN_LEVEL;
#endif
};

#ifndef ASCEND_FACE_USE_HI_MPI
class DecodeH26xInfo {
public:
    VideoDecoder *videoDecoder = nullptr;
    std::shared_ptr<VdecInfo> vdecInfo = nullptr;
    ~DecodeH26xInfo() {}
    DecodeH26xInfo() {}
};
#endif
} // namespace ascendFaceRecognition
#endif